package test_device

import (
	"encoding/json"
	"github.com/gorilla/websocket"
	"http_device/server"
	"log"
	"net"
	"sync"
)

// 客户端直接连接服务器

// 连接服务器, 读取数据, 收到连接，建立tcp连接, 回复成功
// 收发数据

func DemoDevice() {
	conn, _, err := websocket.DefaultDialer.Dial("ws://127.0.0.1:5566/websocket/PU_123", nil)
	if err != nil {
		return
	}

	var (
		connList = map[uint8]*TcpConn{}
		mux      sync.Mutex
	)

	var sendWebsocketMessage = func(conn *websocket.Conn, proto *server.JsonProto) {
		value, _ := json.Marshal(proto)

		mux.Lock()
		defer mux.Unlock()
		_ = conn.WriteMessage(websocket.BinaryMessage, value)
	}

	for {
		_, data, err := conn.ReadMessage()
		if err != nil {
			break
		}

		var object server.JsonProto
		if err = json.Unmarshal(data, &object); err != nil {
			continue
		}

		switch object.Method {
		case server.ProtoMethodConnect:
			c := NewTcpConn(conn, object.ConnId, sendWebsocketMessage)
			if err = c.Dial(); err != nil {
				sendWebsocketMessage(conn, &server.JsonProto{
					Method: server.ProtoMethodClose,
					ConnId: object.ConnId,
				})
			} else {
				connList[object.ConnId] = c
			}
		case server.ProtoMethodMsg:
			if c, ok := connList[object.ConnId]; ok {
				c.Write(object.Data)
			}
		case server.ProtoMethodClose:
			if c, ok := connList[object.ConnId]; ok {
				c.Close()
				delete(connList, object.ConnId)
			}
		}

	}
}

type TcpConn struct {
	sendMsg func(*websocket.Conn, *server.JsonProto)
	conn    *websocket.Conn
	tcp     *net.TCPConn
	connId  uint8
}

func NewTcpConn(conn *websocket.Conn, connId uint8, sendMsg func(*websocket.Conn, *server.JsonProto)) *TcpConn {
	tis := &TcpConn{
		conn:    conn,
		connId:  connId,
		sendMsg: sendMsg,
	}

	return tis
}

func (tis *TcpConn) Dial() error {
	var err error
	tis.tcp, err = net.DialTCP("tcp4", nil, &net.TCPAddr{
		IP:   net.ParseIP("127.0.0.1"),
		Port: 5568,
	})
	if err != nil {
		log.Printf("连接失败[%v]. %v", tis.connId, err)
		return err
	} else {
		log.Printf("连接成功[%v]", tis.connId)
	}

	go func() {
		buff := make([]byte, 1024)
		for {
			n, err := tis.tcp.Read(buff)
			if err != nil {
				log.Printf("读取失败[%v] err: %v", tis.connId, err)
				tis.sendMsg(tis.conn, &server.JsonProto{
					Method: server.ProtoMethodClose,
					ConnId: tis.connId,
				})

				return
			}

			tis.sendMsg(tis.conn, &server.JsonProto{
				Method: server.ProtoMethodMsg,
				ConnId: tis.connId,
				Data:   buff[:n],
			})
		}
	}()

	return nil
}

func (tis *TcpConn) Write(data []byte) {
	_, _ = tis.tcp.Write(data)
}

func (tis *TcpConn) Close() {
	_ = tis.tcp.Close()
}
